<?php
/***************************************************************
*  Copyright notice
*
*  (c) 2008 Andre Jochim (wetter24.de - aktuelles Wetter)
*  All rights reserved
*
*  This script is part of the TYPO3 project. The TYPO3 project is
*  free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  The GNU General Public License can be found at
*  http://www.gnu.org/copyleft/gpl.html.
*
*  This script is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

require_once(PATH_tslib.'class.tslib_pibase.php');


/**
 * Plugin 'News Sitemap' for the 'newssitemap' extension.
 *
 * @author  Meteogroup (André Jochim) <a.jochim@meteogroup.de>
 * @package TYPO3
 * @subpackage  tx_newssitemap
 */


class tx_newssitemap_pi1 extends tslib_pibase {
  var $prefixId = 'tx_newssitemap_pi1';       // Same as class name
  var $scriptRelPath = 'pi1/class.tx_newssitemap_pi1.php';  // Path to this script relative to the extension dir.
  var $extKey = 'newssitemap';          // The extension key.

  #### Standard configuration:
  // fixed configurations (not recommended to change):
  var $itemLimitGeneral     = 1000;   // Google does not allow more
  var $itemLimitUseThis   = 0;    // will be set in the class
  var $sitemapItems   = '';   // going to be filled with the output content
  var $debug      = false;  // for developers (to get some test values)
  var $news_age     = 3;    // In Google's specification it's only allowed to list news not older than 3 days

  // variable configurations:
  var $itemLimitUser    = 100;    // how many news shall the sitemap contain
  var $cachingEnable    = 1;    // if the generated sitemap should be cached in a file
  var $cachingLifetime    = 600;    // in seconds
  var $cachingFolder    = '/var/tmp/';  // save path for the caching file
  var $pid_news_page    = 0;    // Page ID for the single news page
  var $pid_news_folder    = 0;    // Page ID of the folder where the news are stored
  var $publication_name    = '';    // See the Googles's specification
  var $publication_language    = 'en';    // See the Googles's specification
  
  
  /**
   * The main method of the PlugIn
   *
   * @param string    $content: The PlugIn content
   * @param array   $conf: The PlugIn configuration
   * @return  The content that is displayed on the website
   */

  function main($content,$conf) {
    $this->conf=$conf;
    $this->pi_setPiVarDefaults();
    $this->pi_loadLL();
    $this->pi_USER_INT_obj=1; // Configuring so caching is not expected. This value means that no cHash params are ever set. We do this, because it's a USER_INT object!

    // save the current domain of the server
    $this->give_domain();
    
    // process the configurations from TypoScript
    $this->readConfigFromTS($conf);   

    // if caching is switched of OR if there is no valid cached file
    if (!$this->cachingEnable  ||  !$this->readFromCache()){
      if ($this->debug) $this->dump('fetch data live');

      $time1 = microtime(true);

      // create the sitemap items
      $this->getNewsSitemap();
      
      // wrap it with XML main structure
      $this->sitemapItems = '<?xml version="1.0" encoding="UTF-8"?>'.
            '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">'.
              $this->sitemapItems.
            '</urlset>';

      $time2 = microtime(true);
      if ($this->debug) $this->dump($time2-$time1,'time until now (without caching)');
      
      
      // cache it if enabled
      if ($this->cachingEnable){
        $time1 = microtime(true);
        $this->cacheIt();
        $time2 = microtime(true);
        if ($this->debug){
          $this->dump($time2-$time1,'time of caching');
          $this->dump(strlen($this->sitemapItems),'length of xml string');
        }
      }
    }
    elseif ($this->debug) $this->dump('use data from cache');


    # test print out:
    if ($this->debug){
      $this->sitemapItems_ = str_replace(array('<','>'),array('&lt;','&gt;'."\n"),$this->sitemapItems);   
      $this->dump($this->sitemapItems_);
    }
    else  return $this->sitemapItems;
  }
  
  
  
  /**
   * The readConfigFromTS method of the PlugIn
   * if a conf value is set use it
   *
   * @param array   $conf: The PlugIn configuration
   */
   function readConfigFromTS($conf){
    if (isset($conf['itemLimitUser']))      $this->itemLimitUseThis    = $conf['itemLimitUser'];
    else              $this->itemLimitUseThis    = $this->itemLimitUser;
    // if the item limit is too big use the maximum limit value:
    if ($this->itemLimitUseThis > $this->itemLimitGeneral)  $this->itemLimitUseThis = $this->itemLimitGeneral;

    if (isset($conf['cachingEnable']))     $this->cachingEnable     = $conf['cachingEnable'];
    if (isset($conf['cachingLifetime']))      $this->cachingLifetime     = $conf['cachingLifetime'];
    if (isset($conf['cachingFolder']))      $this->cachingFolder     = $conf['cachingFolder'];
    if (isset($conf['pid_news_page']))      $this->pid_news_page     = $conf['pid_news_page'];
    if (isset($conf['pid_news_folder']))      $this->pid_news_folder     = $conf['pid_news_folder'];
    if (isset($conf['publication_name']))      $this->publication_name     = $conf['publication_name'];
    if (isset($conf['publication_language']))      $this->publication_language     = $conf['publication_language'];
    
    // create a unique caching file name for this server with the cachingFolder and further data:
    $this->cachingFile = $this->cachingFolder;
    if (substr($this->cachingFile, strlen($this->cachingFile)-1, 1) != "/") $this->cachingFile .= "/";
    $server_name  = str_replace('.', '_', $_SERVER['SERVER_NAME']);
    $sys_lang = empty($GLOBALS['TSFE']->sys_language_uid) ? '0' : $GLOBALS['TSFE']->sys_language_uid;
    $this->cachingFile .= 'cache_newssitemap_'.$server_name.'_'.$sys_lang.'.tmp';
  }
  
  

  /**
   * The cacheIt method of the PlugIn
   * Save the XML content in the cache file
   */
  function cacheIt(){
    if ($handle = fopen($this->cachingFile, 'w')) {
      fwrite($handle, $this->sitemapItems);
      
      // jetzt noch ranschreiben, wann gecacht:
      $headerdata = array(  'cachetime_int'=>time(),
            'cachetime_str_utc'=>gmdate('Y-m-d H:i:s')
            );
      fwrite($handle, '----headerdata----'.serialize($headerdata));
      fclose($handle);
    }
  }
  


  /**
   * The readFromCache method of the PlugIn
   * Tries to fetch the XML content from the cached file
   *
   * @return  boolean
   */
  function readFromCache(){
    $time1 = microtime(true);
    $return = false; // nur im Erfolgsfall auf true

    @$this->sitemapItems = file_get_contents($this->cachingFile);

    if (!empty($this->sitemapItems)){
      // Header-Daten extrahieren und auswerten
      $pos_header = strpos($this->sitemapItems, '----headerdata----');

      if ($pos_header){
        $headerdata_temp = substr($this->sitemapItems, $pos_header+strlen('----headerdata----') );
        $headerdata = unserialize($headerdata_temp);
        // wenn Cachezeit gefunden + nicht veraltet
        if (isset($headerdata['cachetime_int'])   &&   $headerdata['cachetime_int']+$this->cachingLifetime > time()){
          $this->sitemapItems = substr($this->sitemapItems,0,$pos_header);
          $return = true;
        }
      }
    }
    
    if (!$return) $this->sitemapItems = '';
    $time2 = microtime(true);
    if ($this->debug) $this->dump($time2-$time1,'time for fetching from cache / for checking');
    return $return;
  }
  
  

  /**
   * The getNewsSitemap method of the PlugIn
   * Reads the News from the Database and writes it into a class string
   */
  function getNewsSitemap(){
    $now_int = time();

    // to only show the news not older than a specific time:
    $today_without_time_int = mktime(0, 0, 0, date('m',$now_int), date('d',$now_int), date('Y',$now_int));
    $news_newer_than = $today_without_time_int - ($this->news_age-1)*3600*24;  // -1, because the current day is also one of the allowed days

    $sql_fields = "uid,datetime,keywords,title";
    $sql_from = "tt_news";
    $sql_where =  "pid IN($this->pid_news_folder) AND
        deleted=0 AND
        
        (starttime=0 AND endtime=0  OR  starttime<'$now_int' AND endtime>'$now_int' )
        ";
    $sql_order = "datetime DESC";
    $sql_limit = "$this->itemLimitUseThis";
//print_r($sql_where);
    $time1 = microtime(true);
    $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(  $sql_fields,
                $sql_from,
                $sql_where,
                '',
                $sql_order,
                $sql_limit
                );
    $time2 = microtime(true);

    // traverse the news
    while ($rec = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)){
      // create the news' URL
      // old version -- but this function doesn't generate the cHash
      #$url = $this->pi_getPageLink(  $this->pid_news_page,
      #       '',
      #       array(  'tx_ttnews[tt_news]' => $rec['uid'],
      #         'tx_ttnews[year]' => date('Y',$rec['datetime']),
      #         'tx_ttnews[month]' => date('m',$rec['datetime'])
      #         )
      #       );

      
      // using that function to get the cHash (if is set in the Typo3 system)
      // unfortunately it returns the whole link-tag
      // so we have to extract the url from it
	  $pid_news_page=$this->get_cat_pid($rec['uid'],$this->pid_news_page);

      $params = array(  "parameter" => $pid_news_page,
            "useCacheHash" => 1,
            "additionalParams" => '&tx_ttnews[tt_news]='.$rec['uid'].
                  '&tx_ttnews[year]='.date('Y',$rec['datetime']).
                  '&tx_ttnews[month]='.date('m',$rec['datetime']),
            "ATagParams" => ""
            );
      $url = $this->cObj->typoLink('dummy', $params); 

      $matches = array();
      preg_match('|<a.*href="(.*)".*>.*</a>|Ui', $url, $matches);

      // add the XML content of the news to the class string
      if (!empty($matches[1])){
        $this->sitemapItems .= $this->generateNewsItem($matches[1], $rec['datetime'], $rec['title'], $rec['keywords']);
      }
    }
    
    mysql_free_result($res);
  }
	function get_cat_pid($uid,$single_pid)
	{
		$where = 'uid_local='.$uid;
		$res =  $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid_foreign','tt_news_cat_mm',$where,'','sorting',1);

		while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))
		{
			$uid_foreign=$row['uid_foreign'];
		}
		if($uid_foreign>0)
		{
			$where = 'deleted=0 AND hidden=0 AND uid='.$uid_foreign;
			$res =  $GLOBALS['TYPO3_DB']->exec_SELECTquery('single_pid','tt_news_cat',$where,'','sorting');
	
			while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))
			{
				$single_pid=$row['single_pid']?$row['single_pid']:$single_pid;
			}
		}
		return $single_pid;
	}

  /**
   * The generateNewsItem method of the PlugIn
   * Returns the XML content of the news
   *
   * @param string    $url: news URL
   * @param int   $creation_date: Timestamp of news creation
   * @param string    $keywords: Keywords (optional)
   * @return  string
   */
  function generateNewsItem($url, $creation_date, $title, $keywords=''){
    $keywords = trim($keywords);
    
    if (empty($keywords)) $keywords_add = '';
    else      $keywords_add = '<news:keywords>'.$keywords.'</news:keywords>';
    
    // damit fuer Google nicht alle zur gleichen Zeit erstellt wurden: Streuung um x Sekunden (bis zu n Tage kann eine Seite für Google "alt" sein)
    return  "<url>".
        "<loc>{$this->domain}".$url."</loc>".
        "<news:news>".
          "<news:publication_date>".gmdate("Y-m-d\TH:i:s\Z", $creation_date)."</news:publication_date>".
          "<news:title>".$title."</news:title>".
          "<news:publication>".
            "<news:name>".$this->publication_name."</news:name>".
            "<news:language>".$this->publication_language."</news:language>".
          "</news:publication>".
          $keywords_add.
        "</news:news>".
      "</url>";
  }



  /**
   * The give_domain method of the PlugIn
   * Sets the server domain and the protocol
   */
  function give_domain(){
    $url = $_SERVER["SERVER_NAME"];

    if (substr($url, 0, 7) != "http://")    $url = "http://".$url;
    if (substr($url, strlen($url)-1, 1) != "/") $url .= "/";
    
    $this->domain = $url;
  }



  /**
   * The dump method of the PlugIn
   * Prints out a debug box immediately
   *
   * @param string    $val: debug text
   * @param string    $head: debug headline
   */ 
  function dump($val,$head=''){
    if (!$this->debug) return;
    
    echo '<div style="border:1px solid gray;background-color:#e8e8e8;margin-bottom:3px;font-size:11px">';
    if (!empty($head)) echo "<b>$head</b>";
    echo '<pre>';
    print_r($val);
    echo '</pre></div>';
  }
  
}



if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/newssitemap/pi1/class.tx_newssitemap_pi1.php'])  {
  include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/newssitemap/pi1/class.tx_newssitemap_pi1.php']);
}

?>